#ifndef MOONLIGHT_OHOS_TRACKPADEMULATOR_H
#define MOONLIGHT_OHOS_TRACKPADEMULATOR_H

#include "AbstractTouchScreenControlHandler.h"
#include "core/utils/CancellableTimer.h"
#include <cstdint>
#include <mutex>
#include <deque>
#include <memory>
#include <chrono>


class TrackpadEmulator : public AbstractTouchScreenControlHandler {
public:
    TrackpadEmulator(const Config &overrides);
    ~TrackpadEmulator() override;
    void handle(OH_NativeXComponent *const xcomp, void *const win, const TouchEvent &touchEvent) override;

private:
    void applyConfig(const std::unordered_map<std::string, std::string> &overrides) override;

private:
    ATSCH_DEFINE_CONFIG(double, moveAcceleration, 1);
    ATSCH_DEFINE_CONFIG(double, scrollAcceleration, 2);
    ATSCH_DEFINE_CONFIG(int32_t, tapTimeoutMs, 100);
    ATSCH_DEFINE_CONFIG(int32_t, deadzonePx, 10);
    ATSCH_DEFINE_CONFIG(int32_t, gestureComboTimeoutMs, 300);

    const static std::chrono::microseconds pollDelay;

    mutable std::mutex mtx;

    struct Coord {
        float x, y;
    };
    struct FingerTap {
        Coord whenDown;
        Coord current;
    };
    std::unordered_map<int32_t, FingerTap> fingerSet = {};
    int8_t maxTapFingers = 0;
    std::unique_ptr<CancellableTimer> tapTimer = nullptr;
    enum class TapState {
        None, Tapping, Holding,
    } tapState = TapState::None;

    enum class AtomicGestureType {
        Tap, HoldStart, HoldEnd,
    };
    struct GestureQueueItem {
        AtomicGestureType gesture;
        int8_t fingers;
    };
    std::deque<const GestureQueueItem> generatedGestures = {};
    std::unique_ptr<CancellableTimer> gestureTimer = nullptr;
    enum class GestureComboState {
        None, SingleFingerTapped, SingleFingerTappedThenHolding, NonComboHolding,
    } gestureComboState = GestureComboState::None;

    enum class ActionType {
        LeftClick, RightClick, MiddleClick,
        Move, Drag, Scroll,
    };
    struct IAction {
        IAction(const ActionType &type);
        virtual ~IAction();
        const ActionType type;
        virtual void handle(const Coord &deltaCenter) = 0;
    };
    struct BaseClickAction;
    struct LeftClickAction;
    struct RightClickAction;
    struct MiddleClickAction;
    struct MoveAction;
    struct DragAction;
    struct ScrollAction;
    std::unique_ptr<IAction> currentAction = nullptr;

    void handleTapState(OH_NativeXComponent *const xcomp, const TouchEvent &ev, Coord &deltaCenter);
    void handleGestureCombo();
    void handleAction(const Coord &deltaCenter);

};

#endif //MOONLIGHT_OHOS_TRACKPADEMULATOR_H
